React'ning useFormStatus hook'idan foydalanib bajarilish holatini baholash va yakunlanish vaqtini bashorat qilishni o'rganing, bu esa katta hajmli ma'lumotlar bilan ishlovchi ilovalarda foydalanuvchi tajribasini yaxshilaydi.
React useFormStatus Bajarilish Holatini Baholash: Yakunlanish Vaqtini Bashorat Qilish
React 18 versiyasida taqdim etilgan React'ning useFormStatus hook'i formani yuborish holati haqida qimmatli ma'lumot beradi. U to'g'ridan-to'g'ri bajarilish holatini baholashni taklif qilmasa-da, biz uning xususiyatlari va boshqa usullardan foydalanib, uzoq davom etishi mumkin bo'lgan formani yuborish jarayonlarida foydalanuvchilarga mazmunli fikr-mulohazalarni taqdim etishimiz mumkin. Ushbu postda useFormStatus'dan foydalanganda bajarilish holatini baholash va yakunlanish vaqtini bashorat qilish usullari ko'rib chiqiladi, bu esa yanada qiziqarli va foydalanuvchilar uchun qulay tajribaga olib keladi.
useFormStatus'ni Tushunish
Bajarilish holatini baholashga kirishishdan oldin, useFormStatus'ning vazifasini tezda eslab o'tamiz. Ushbu hook action prop'idan foydalanadigan <form> elementi ichida ishlatish uchun mo'ljallangan. U quyidagi xususiyatlarni o'z ichiga olgan obyektni qaytaradi:
pending: Formaning hozirda yuborilayotganligini ko'rsatuvchi mantiqiy qiymat.data: Forma bilan yuborilgan ma'lumotlar (agar yuborish muvaffaqiyatli bo'lsa).method: Formani yuborish uchun ishlatilgan HTTP usuli (masalan, 'POST', 'GET').action: Formaningactionprop'iga uzatilgan funksiya.error: Agar yuborish muvaffaqiyatsiz bo'lsa, xatolik obyekti.
useFormStatus bizga formaning yuborilayotganligini aytsa-da, yuborish jarayonining borishi haqida, ayniqsa action funksiyasi murakkab yoki uzoq davom etadigan operatsiyalarni o'z ichiga olsa, to'g'ridan-to'g'ri ma'lumot bermaydi.
Bajarilish Holatini Baholashdagi Qiyinchilik
Asosiy qiyinchilik shundaki, action funksiyasining bajarilishi React uchun shaffof emas. Biz jarayon qanchalik oldinga siljiganini bilmaymiz. Bu, ayniqsa, server tomonidagi operatsiyalar uchun to'g'ri keladi. Biroq, biz bu cheklovni yengish uchun turli strategiyalarni qo'llashimiz mumkin.
Bajarilish Holatini Baholash Strategiyalari
Bu yerda siz qo'llashingiz mumkin bo'lgan bir nechta yondashuvlar keltirilgan, ularning har birining o'z afzalliklari va kamchiliklari bor:
1. Server-Sent Events (SSE) yoki WebSockets
Eng ishonchli yechim ko'pincha serverdan mijozga bajarilish holati yangilanishlarini yuborishdir. Bunga quyidagilar yordamida erishish mumkin:
- Server-Sent Events (SSE): Serverga bitta HTTP ulanishi orqali mijozga yangilanishlarni yuborish imkonini beruvchi bir tomonlama (serverdan-mijozga) protokol. SSE mijoz faqat yangilanishlarni *qabul qilishi* kerak bo'lganda idealdir.
- WebSockets: Mijoz va server o'rtasida doimiy ulanishni ta'minlaydigan ikki tomonlama aloqa protokoli. WebSockets har ikki yo'nalishda ham real vaqtda yangilanishlar uchun mos keladi.
Misol (SSE):
Server tomoni (Node.js):
const express = require('express');
const app = express();
app.get('/progress', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.flushHeaders();
let progress = 0;
const interval = setInterval(() => {
progress += 10;
if (progress > 100) {
progress = 100;
clearInterval(interval);
res.write(`data: {"progress": ${progress}, "completed": true}\n\n`);
res.end();
} else {
res.write(`data: {"progress": ${progress}, "completed": false}\n\n`);
}
}, 500); // Har 500msda bajarilish holatini yangilashni simulyatsiya qilish
});
app.listen(3000, () => {
console.log('Server 3000-portda ishlamoqda');
});
Mijoz tomoni (React):
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [progress, setProgress] = useState(0);
useEffect(() => {
const eventSource = new EventSource('/progress');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
setProgress(data.progress);
if (data.completed) {
eventSource.close();
}
};
eventSource.onerror = (error) => {
console.error('EventSource ishlamadi:', error);
eventSource.close();
};
return () => {
eventSource.close();
};
}, []);
return (
<div>
<p>Bajarilish holati: {progress}%</p>
</div>
);
}
export default MyComponent;
Izoh:
- Server SSE uchun tegishli sarlavhalarni o'rnatadi.
- Server bajarilish holati yangilanishlarini
data:hodisalari sifatida yuboradi. Har bir hodisaprogressvacompletedbayrog'ini o'z ichiga olgan JSON obyekti hisoblanadi. - React komponenti ushbu hodisalarni tinglash uchun
EventSource'dan foydalanadi. - Komponent qabul qilingan hodisalar asosida holatni (
progress) yangilaydi.
Afzalliklari: Bajarilish holatining aniq yangilanishlari, real vaqtdagi fikr-mulohazalar.
Kamchiliklari: Server tomonida o'zgarishlarni talab qiladi, murakkabroq amalga oshirish.
2. API Endpoint orqali So'rov Yuborish (Polling)
Agar siz SSE yoki WebSockets'dan foydalana olmasangiz, so'rov yuborish (polling) usulini qo'llashingiz mumkin. Mijoz operatsiya holatini tekshirish uchun serverga vaqti-vaqti bilan so'rovlar yuboradi.
Misol:
Server tomoni (Node.js):
const express = require('express');
const app = express();
// Uzoq davom etadigan vazifani simulyatsiya qilish
let taskProgress = 0;
let taskId = null;
app.post('/start-task', (req, res) => {
taskProgress = 0;
taskId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); // Noyob vazifa ID'sini yaratish
// Fon rejimida qayta ishlashni simulyatsiya qilish
const interval = setInterval(() => {
taskProgress += 10;
if (taskProgress >= 100) {
taskProgress = 100;
clearInterval(interval);
}
}, 500);
res.json({ taskId });
});
app.get('/task-status/:taskId', (req, res) => {
if (req.params.taskId === taskId) {
res.json({ progress: taskProgress });
} else {
res.status(404).json({ message: 'Vazifa topilmadi' });
}
});
app.listen(3000, () => {
console.log('Server 3000-portda ishlamoqda');
});
Mijoz tomoni (React):
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [progress, setProgress] = useState(0);
const [taskId, setTaskId] = useState(null);
const startTask = async () => {
const response = await fetch('/start-task', { method: 'POST' });
const data = await response.json();
setTaskId(data.taskId);
};
useEffect(() => {
if (!taskId) return;
const interval = setInterval(async () => {
const response = await fetch(`/task-status/${taskId}`);
const data = await response.json();
setProgress(data.progress);
if (data.progress === 100) {
clearInterval(interval);
}
}, 1000); // Har 1 soniyada so'rov yuborish
return () => clearInterval(interval);
}, [taskId]);
return (
<div>
<button onClick={startTask} disabled={taskId !== null}>Vazifani Boshlash</button>
{taskId && <p>Bajarilish holati: {progress}%</p>}
</div>
);
}
export default MyComponent;
Izoh:
- Mijoz
/start-task'ni chaqirib, vazifani boshlaydi vataskIdoladi. - So'ngra mijoz bajarilish holatini olish uchun vaqti-vaqti bilan
/task-status/:taskId'ga so'rov yuboradi.
Afzalliklari: Amalga oshirish nisbatan oson, doimiy ulanishlarni talab qilmaydi.
Kamchiliklari: SSE/WebSockets'ga qaraganda kamroq aniq bo'lishi mumkin, so'rovlar oralig'i tufayli kechikishlarni keltirib chiqaradi, tez-tez so'rovlar tufayli serverga yuklama tushiradi.
3. Optimistik Yangilanishlar va Evristika
Ba'zi hollarda, oqilona baholashni ta'minlash uchun evristika bilan birlashtirilgan optimistik yangilanishlardan foydalanishingiz mumkin. Masalan, agar siz fayllarni yuklayotgan bo'lsangiz, mijoz tomonida yuklangan baytlar sonini kuzatib borishingiz va umumiy fayl hajmiga asoslanib bajarilish holatini baholashingiz mumkin.
Misol (Fayl Yuklash):
import React, { useState } from 'react';
function MyComponent() {
const [progress, setProgress] = useState(0);
const [file, setFile] = useState(null);
const handleFileChange = (event) => {
setFile(event.target.files[0]);
};
const handleSubmit = async (event) => {
event.preventDefault();
if (!file) return;
const formData = new FormData();
formData.append('file', file);
try {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentage = Math.round((event.loaded * 100) / event.total);
setProgress(percentage);
}
});
xhr.open('POST', '/upload'); // O'zingizning yuklash endpoint'ingiz bilan almashtiring
xhr.send(formData);
xhr.onload = () => {
if (xhr.status === 200) {
console.log('Yuklash tugallandi!');
} else {
console.error('Yuklash muvaffaqiyatsiz bo\'ldi:', xhr.status);
}
};
xhr.onerror = () => {
console.error('Yuklash muvaffaqiyatsiz bo\'ldi');
};
} catch (error) {
console.error('Yuklash xatosi:', error);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="file" onChange={handleFileChange} />
<button type="submit" disabled={!file}>Yuklash</button>
</form>
<p>Bajarilish holati: {progress}%</p>
</div>
);
}
export default MyComponent;
Izoh:
- Komponent faylni yuklash uchun
XMLHttpRequestobyektidan foydalanadi. xhr.upload'dagiprogresshodisasini tinglovchi yuklanish jarayonini kuzatish uchun ishlatiladi.- Hodisaning
loadedvatotalxususiyatlari bajarilgan foizni hisoblash uchun ishlatiladi.
Afzalliklari: Faqat mijoz tomonida ishlaydi, darhol fikr-mulohaza bildirish imkonini beradi.
Kamchiliklari: Aniqlik evristikaning ishonchliligiga bog'liq, barcha turdagi operatsiyalar uchun mos kelmasligi mumkin.
4. Harakatni Kichikroq Qadamlarga Bo'lish
Agar action funksiyasi bir nechta alohida qadamlarni bajarsa, har bir qadamdan so'ng bajarilish holatini ko'rsatish uchun UI'ni yangilashingiz mumkin. Bu action funksiyasini yangilanishlarni ta'minlash uchun o'zgartirishni talab qiladi.
Misol:
import React, { useState } from 'react';
async function myAction(setProgress) {
setProgress(10);
await someAsyncOperation1();
setProgress(40);
await someAsyncOperation2();
setProgress(70);
await someAsyncOperation3();
setProgress(100);
}
function MyComponent() {
const [progress, setProgress] = useState(0);
const handleSubmit = async () => {
await myAction(setProgress);
};
return (
<div>
<form onSubmit={handleSubmit}>
<button type="submit">Yuborish</button>
</form>
<p>Bajarilish holati: {progress}%</p>
</div>
);
}
export default MyComponent;
Izoh:
myActionfunksiyasisetProgresscallback'ini qabul qiladi.- U bajarilish jarayonida turli nuqtalarda bajarilish holatini yangilaydi.
Afzalliklari: Bajarilish holati yangilanishlari ustidan to'g'ridan-to'g'ri nazorat.
Kamchiliklari: action funksiyasini o'zgartirishni talab qiladi, agar qadamlar oson bo'linmasa, amalga oshirish murakkabroq bo'lishi mumkin.
Yakunlanish Vaqtini Bashorat Qilish
Bajarilish holati yangilanishlariga ega bo'lganingizdan so'ng, ulardan qolgan taxminiy vaqtni bashorat qilish uchun foydalanishingiz mumkin. Oddiy yondashuv - ma'lum bir bajarilish darajasiga erishish uchun ketgan vaqtni kuzatib borish va umumiy vaqtni taxmin qilish uchun ekstrapolyatsiya qilishdir.
Misol (Soddalashtirilgan):
import React, { useState, useEffect, useRef } from 'react';
function MyComponent() {
const [progress, setProgress] = useState(0);
const [estimatedTimeRemaining, setEstimatedTimeRemaining] = useState(null);
const startTimeRef = useRef(null);
useEffect(() => {
if (progress > 0 && startTimeRef.current === null) {
startTimeRef.current = Date.now();
}
if (progress > 0) {
const elapsedTime = Date.now() - startTimeRef.current;
const estimatedTotalTime = (elapsedTime / progress) * 100;
const remainingTime = estimatedTotalTime - elapsedTime;
setEstimatedTimeRemaining(Math.max(0, remainingTime)); // Manfiy bo'lmasligini ta'minlash
}
}, [progress]);
// ... (komponentning qolgan qismi va avvalgi bo'limlarda tasvirlangan bajarilish holati yangilanishlari)
return (
<div>
<p>Bajarilish holati: {progress}%</p>
{estimatedTimeRemaining !== null && (
<p>Qolgan taxminiy vaqt: {Math.round(estimatedTimeRemaining / 1000)} soniya</p>
)}
</div>
);
}
export default MyComponent;
Izoh:
- Bajarilish holati birinchi marta yangilanganda boshlanish vaqtini saqlaymiz.
- O'tgan vaqtni hisoblaymiz va undan umumiy vaqtni taxmin qilish uchun foydalanamiz.
- Taxminiy umumiy vaqtdan o'tgan vaqtni ayirib, qolgan vaqtni hisoblaymiz.
Muhim Jihatlar:
- Aniqlik: Bu *juda* soddalashtirilgan bashorat. Tarmoq sharoitlari, server yuklamasi va boshqa omillar aniqlikka sezilarli ta'sir ko'rsatishi mumkin. Bir nechta intervallar bo'yicha o'rtacha hisoblash kabi murakkabroq usullar aniqlikni oshirishi mumkin.
- Vizual Fikr-mulohaza: Vaqt *taxminiy* ekanligini aniq ko'rsating. Diapazonlarni ko'rsatish (masalan, "Qolgan taxminiy vaqt: 5-10 soniya") yanada realistik bo'lishi mumkin.
- Noodatiy Holatlar: Dastlab bajarilish holati juda sekin bo'lgan noodatiy holatlarni boshqaring. Nolga bo'lishdan yoki haddan tashqari katta taxminlarni ko'rsatishdan saqlaning.
useFormStatus'ni Bajarilish Holatini Baholash bilan Birlashtirish
useFormStatus o'zi bajarilish holati haqida ma'lumot bermasa-da, uning pending xususiyatidan bajarilish indikatorini yoqish yoki o'chirish uchun foydalanishingiz mumkin. Masalan:
import React, { useState } from 'react';
import { useFormStatus } from 'react-dom';
// ... (Oldingi misollardan olingan bajarilish holatini baholash mantig'i)
function MyComponent() {
const [progress, setProgress] = useState(0);
const { pending } = useFormStatus();
const handleSubmit = async (formData) => {
// ... (Sizning formani yuborish mantig'ingiz, shu jumladan bajarilish holatini yangilash)
};
return (
<form action={handleSubmit}>
<button type="submit" disabled={pending}>Yuborish</button>
{pending && <p>Bajarilish holati: {progress}%</p>}
</form>
);
}
Ushbu misolda bajarilish indikatori faqat forma kutilayotgan (pending) holatda bo'lganda (ya'ni, useFormStatus.pending true bo'lganda) ko'rsatiladi.
Eng Yaxshi Amaliyotlar va E'tiborga Olinadigan Jihatlar
- Aniqlikka Ustunlik Bering: Bajarilayotgan operatsiya turiga mos keladigan bajarilish holatini baholash usulini tanlang. SSE/WebSockets odatda eng aniq natijalarni beradi, evristika esa oddiyroq vazifalar uchun yetarli bo'lishi mumkin.
- Aniq Vizual Fikr-mulohaza Taqdim Eting: Operatsiya bajarilayotganligini ko'rsatish uchun progress barlar, spinnerlar yoki boshqa vizual belgilardan foydalaning. Bajarilish indikatorini va, agar mavjud bo'lsa, qolgan taxminiy vaqtni aniq belgilang.
- Xatoliklarni To'g'ri Boshqaring: Agar operatsiya davomida xatolik yuz bersa, foydalanuvchiga ma'lumot beruvchi xato xabarini ko'rsating. Bajarilish indikatorining ma'lum bir foizda qotib qolishiga yo'l qo'ymang.
- Ishlash Samaradorligini Optimallashtiring: UI asosiy oqimida hisoblash jihatidan qimmat operatsiyalarni bajarishdan saqlaning, chunki bu ishlashga salbiy ta'sir ko'rsatishi mumkin. Ishni fon oqimlariga o'tkazish uchun veb-ishchilar (web workers) yoki boshqa usullardan foydalaning.
- Mavjudlik (Accessibility): Bajarilish indikatorlari nogironligi bo'lgan foydalanuvchilar uchun mavjud ekanligiga ishonch hosil qiling. Operatsiya bajarilishi haqida semantik ma'lumot berish uchun ARIA atributlaridan foydalaning. Masalan, progress barda
aria-valuenow,aria-valueminvaaria-valuemax'dan foydalaning. - Mahalliylashtirish (Localization): Qolgan taxminiy vaqtni ko'rsatayotganda, turli vaqt formatlari va mintaqaviy afzalliklarni yodda tuting. Foydalanuvchining lokali uchun vaqtni to'g'ri formatlash uchun
date-fnsyokimoment.jskabi kutubxonalardan foydalaning. - Xalqarolashtirish (Internationalization): Xato xabarlari va boshqa matnlar bir nechta tillarni qo'llab-quvvatlash uchun xalqarolashtirilishi kerak. Tarjimalarni boshqarish uchun
i18nextkabi kutubxonadan foydalaning.
Xulosa
React'ning useFormStatus hook'i to'g'ridan-to'g'ri bajarilish holatini baholash imkoniyatlarini taqdim etmasa-da, uni boshqa usullar bilan birlashtirib, foydalanuvchilarga formani yuborish paytida mazmunli fikr-mulohazalarni taqdim etishingiz mumkin. SSE/WebSockets, so'rov yuborish (polling), optimistik yangilanishlar yoki harakatlarni kichikroq qadamlarga bo'lish orqali siz yanada qiziqarli va foydalanuvchilar uchun qulay tajriba yaratishingiz mumkin. Joylashuvi yoki kelib chiqishidan qat'i nazar, barcha foydalanuvchilar uchun ijobiy tajribani ta'minlash uchun aniqlikka ustunlik berishni, aniq vizual fikr-mulohaza berishni, xatolarni to'g'ri boshqarishni va ishlash samaradorligini optimallashtirishni unutmang.